package get_advertiser_fund

import (
	oceanApi "cid-media-api/api/ocean"
	"cid-media-api/global"
	"cid-media-api/models"
	"github.com/robfig/cron/v3"
	"github.com/samber/lo"
	"gorm.io/gorm/clause"
	"log"
	"sync"
	"time"
)

func Run() {
	c := cron.New()
	c.AddFunc("*/2 * * * *", func() {

		startTime := time.Now().Format(time.DateTime)
		log.Printf("====================================================")
		log.Printf("正在定时执行账户余额获取任务")
		log.Printf("任务开始时间： %v", startTime)

		Execute(0)

		endTime := time.Now().Format(time.DateTime)
		log.Printf("任务结束时间： %v", endTime)
		log.Printf("====================================================")

	})

	c.Run()
}

func Execute(advertiserID int) {
	var mediaAccounts []models.MediaAccount

	insertCount := 0
	updateCount := 0

	db := global.CidDb.Where("status = ?", 1).Where("media_id = ?", oceanApi.MediaIdOcean)

	if advertiserID > 0 {
		db = db.Where("advertiser_id = ?", advertiserID)
	}

	err := db.Find(&mediaAccounts).Error

	if err != nil {
		print(err)
	}

	const chunkSize = 800 //分批处理
	for _, accountBatches := range lo.Chunk(mediaAccounts, chunkSize) {
		var apiBatchData []models.MediaAccountFund
		apiBatchDataChan := make(chan models.MediaAccountFund)
		var wg sync.WaitGroup

		for _, account := range accountBatches {
			wg.Add(1)
			go func() {
				data := oceanApi.GetAdvertiserFund(account)

				if data == nil {
					return
				}

				apiBatchDataChan <- models.MediaAccountFund{
					MediaId:        oceanApi.MediaIdOcean,
					MediaAccountId: account.MediaAccountId,
					AdvertiserId:   account.AdvertiserId,
					AdvertiserName: account.AdvertiserName,
					Balance:        *data.Balance,
				}
			}()
		}

		go func() {
			for range accountBatches {
				select {
				case item := <-apiBatchDataChan:
					apiBatchData = append(apiBatchData, item)
					wg.Done()
				}
			}
		}()

		wg.Wait()

		if len(apiBatchData) > 0 {
			advertiserIDs := lo.Map(apiBatchData, func(item models.MediaAccountFund, idx int) int64 {
				return item.AdvertiserId
			})

			var existingRecords []models.MediaAccountFund
			var newRecords []models.MediaAccountFund
			var updatedRecords []models.MediaAccountFund

			err = global.CidDb.Where("advertiser_id in (?)", advertiserIDs).Find(&existingRecords).Error

			lo.ForEach(apiBatchData, func(abd models.MediaAccountFund, idx int) {

				existedRecord, isExisted := lo.Find(existingRecords, func(record models.MediaAccountFund) bool {
					return record.AdvertiserId == abd.AdvertiserId
				})

				if isExisted {
					if existedRecord.Balance != abd.Balance {
						updatedRecords = append(updatedRecords, abd)
						updateCount += 1
					}
				} else {
					newRecords = append(newRecords, abd)
					insertCount += 1
				}
			})

			if len(updatedRecords) > 0 {
				global.CidDb.Clauses(clause.OnConflict{
					Columns:   []clause.Column{{Name: "advertiser_id"}},
					DoUpdates: clause.AssignmentColumns([]string{"balance", "advertiser_name", "media_account_id"}),
				}).Create(&updatedRecords)
			}

			if len(newRecords) > 0 {
				global.CidDb.Create(&newRecords)
			}
		}

	}

	log.Printf("插入数量：%v", insertCount)
	log.Printf("更新数量：%v", updateCount)
}
